package com.gujiangbo.mapstruct;

import java.util.HashMap;
import java.util.stream.IntStream;

public class DataUtil {

    public static HashMap<String, Integer> hashMap = new HashMap<>();

    // 数据初始化
    static {
        IntStream.range(0, 26).forEach(v -> {
            hashMap.put(String.valueOf((char) (v + 65)), v);
            hashMap.put(String.valueOf((char) (v + 97)), v + 26);
            if (v < 10) hashMap.put(String.valueOf(v), v + 52);
        });
        hashMap.put("+", 62);
        hashMap.put("/", 63);
    }


    /*
    * Oracle的物理扩展ROWID有18位，
    * 每位采用64位编码，分别用A~Z、a~z、0~9、+、/共64个字符表示。
      A表示0，B表示1，……Z表示25，
      a表示26，……z表示51，
      0表示52，……，9表示61，
      +表示62，/表示63
    * */


    /**
     * 保存rowid需要10个字节或者是80个位二进制位。这80个二进制位分别是：
     * 1. 数据对象编号，表明此行所属的数据库对象的编号，每个数据对象在数据库建立的时候都被唯一分配一个编号，并且此编号唯一。数据对象编号占用大约32位，（6位显示）。
     * 2. 对应文件编号，表明该行所在文件的编号，表空间的每一个文件标号都是唯一的。文件编号所占用的位置是10位（3位显示）。
     * 3. 块编号，表明改行所在文件的块的位置块编号需要22位（6位显示）。
     * 4. 行编号，表明该行在行目录中的具体位置行编号需要16位（3位显示）。
     * 这样加起来就是80位。
     *
     * @param rowID
     * @return
     */
    public static void conversion(String rowID) {
        //AAAbn2AAEAAAAh7AAT
        //AAAbn2 AAE AAAAh7 AAT
        if (rowID.length() != 18) {
            throw new RuntimeException("rowID length fault");
        }
        String object = rowID.substring(0, 6);
        String file = rowID.substring(6, 9);
        String block = rowID.substring(9, 15);
        String row = rowID.substring(15, 18);
        System.out.println("rowID:" + rowID);
        System.out.println("数据对象编号:" + calculate(object.toCharArray()));
        System.out.println("对应文件编号:" + calculate(file.toCharArray()));
        System.out.println("块编号:" + calculate(block.toCharArray()));
        System.out.println("行编号:" + calculate(row.toCharArray()));
    }

    private static int calculate(char[] chars) {
        int result = 0;
        if (chars == null || chars.length == 0) return result;
        for (int i = 0; i < chars.length; i++) {
            result += (int) (hashMap.get(String.valueOf(chars[i])) * Math.pow(64, chars.length - i - 1));
        }
        return result;
    }

    public static void main(String[] args) {
        conversion("AAAbn2AAEAAAAh7AAT");
        conversion("AAAbn2AAEAAAAh7AAS");
    }
}
